(function($){
	var KEY = "jforest.edit";
	
	var _IERANGE = !window.getSelection;
	
	function _escape(val) {
		return val.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
	}
	function _unescape(val) {
		return val.replace(/&lt;/g, '<').replace(/&gt;/g, '>').replace(/&quot;/g, '"').replace(/&amp;/g, '&');
	}
	
	var Edit = function(options){
		this.options = $.extend({
			changeCallback:function(){}
		},options);
	};

	Edit.prototype = {
		_createIframe:function($el){
			this.$iframe = $('<iframe frameborder="0" marginheight="0" marginwidth="0" scrolling="no" width="100%"></iframe>');
			$el.append(this.$iframe);
			var doc = this.getDoc();
			doc.open();
			doc.write('<!DOCTYPE html><html lang="zh"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"></head><body></body></html>');
			doc.close();
			doc.designMode = 'on';
			var edit = this;
			$(doc.body).keyup(function(event){
				edit.$iframe.height($(edit.getDoc().body).height());
				edit.options.changeCallback.apply(edit,[event]);
			});
			return this
		},
		getDoc:function(){
			return this.$iframe[0].contentDocument || this.$iframe[0].contentWindow.document;
		},
		getWin:function(){
			var doc = this.getDoc();
			return doc.parentWindow || doc.defaultView;
		},
		getSelection:function(){	
			var doc = this.getDoc(),win = this.getWin();
			return _IERANGE ? doc.selection : win.getSelection();
		},
		getRange:function(){
			var sel = this.getSelection(),rng;
			try {
				if (sel.rangeCount > 0) {
					rng = sel.getRangeAt(0);
				} else {
					rng = sel.createRange();
				}
			}catch(e){}
			return rng; 
		},
		//加粗
		bold:function(){
			var rng = this.getRange(),doc = this.getDoc();
			if(rng){try{doc.execCommand("Bold");}catch(e){}}
		},
		//斜体
		italic:function(){
			var rng = this.getRange(),doc = this.getDoc();
			if(rng){try{doc.execCommand("Italic");}catch(e){}}
		},
		//设置字体大小
		fontSize:function(size){
			var rng = this.getRange(),doc = this.getDoc();
			if(rng){try{doc.execCommand("FontSize",false,size);}catch(e){}}
		},
		//设置字体颜色
		foreColor:function(color){
			var rng = this.getRange(),doc = this.getDoc();
			if(rng){try{doc.execCommand("ForeColor",false,color);}catch(e){}}
		},
		//设置背景颜色
		backColor:function(color){
			var rng = this.getRange(),doc = this.getDoc();
			if(rng){try{doc.execCommand("BackColor",false,color);}catch(e){}}
		},
		center:function(){
			var rng = this.getRange(),doc = this.getDoc();
			if(rng){try{doc.execCommand("JustifyCenter");}catch(e){}}
		},
		right:function(){
			var rng = this.getRange(),doc = this.getDoc();
			if(rng){try{doc.execCommand("JustifyRight");}catch(e){}}
		},
		left:function(){
			var rng = this.getRange(),doc = this.getDoc();
			if(rng){try{doc.execCommand("JustifyLeft");}catch(e){}}
		},
		//拷贝选择的内容到剪贴板
		copy:function(){
			var rng = this.getRange(),doc = this.getDoc();
			if(rng){try{doc.execCommand("Copy");}catch(e){}}
		},
		indent:function(){
			var rng = this.getRange(),doc = this.getDoc();
			if(rng){try{doc.execCommand("Indent");}catch(e){}}
		},
		outdent:function(){
			var rng = this.getRange(),doc = this.getDoc();
			if(rng){try{doc.execCommand("Outdent");}catch(e){}}
		},
		//包裹选中内容
		wrap:function(el){
			var rng = this.getRange();
			if(rng && rng.startOffset != rng.endOffset){
				try{
					var $node = $(el).html(rng.cloneContents());
					rng.deleteContents();
					rng.insertNode($node[0]);
				}catch(e){}
			}
		},
		//替换选中内容
		replace:function(val){
			var rng = this.getRange(),doc = this.getDoc();
			if(rng && rng.startOffset != rng.endOffset){
				try{
					var node = doc.createTextNode(val);
					rng.deleteContents();
					rng.insertNode(node);
				}catch(e){}
			}
		},
		//在光标处插入内容
		insert:function(val){
			if(val){
				var rng = this.getRange(),doc = this.getDoc();
				if(rng){
					try{
						if(/<[^>]+>/g.test(val)){
							rng.insertNode($(val)[0]);
						}else{
							var node = doc.createTextNode(val);
							rng.insertNode(node);
						}
					}catch(e){}
				}
			}
		},
		//删除选中内容
		delRange:function(){
			var rng = this.getRange();
			if(rng){try{rng.deleteContents();}catch(e){}}
		},
		//移除格式化标签
		removeFormat:function(){
			var rng = this.getRange(),doc = this.getDoc();
			if(rng){try{doc.execCommand("RemoveFormat");}catch(e){}}
		},
		//移除超链接
		unlink:function(){
			var rng = this.getRange(),doc = this.getDoc();
			if(rng){try{doc.execCommand("Unlink");}catch(e){}}
		},
		//获取所有内容
		html:function(val){
			var doc = this.getDoc();
			if(val){$(doc.body).html(val);this.$iframe.height($(this.getDoc().body).height());return this;}
			else{return $(doc.body).html();}
		}
	};
	/* 编辑器外壳 */
	var EditShell = function(element,options){
		this.options = $.extend({
			height:'300px'
		},options);
		
		this.$el = $('<div class="panel panel-info"><div class="panel-heading"></div><div class="panel-body" style="height:'+this.options.height+'"></div></div>');
		$(element).parent().append(this.$el);
		this.$textarea = $(element).hide().appendTo(this.$el.find('.panel-body'));
		
		var shell = this;
		this.edit = new Edit({
			changeCallback:function(){
				shell.$textarea.val(this.html());
			}
		})._createIframe(this.$el.find('.panel-body'));
		$(this.$el.find('.panel-body')).niceScroll({styler:"fb",cursorcolor:"#d9edf7", cursorwidth:'6',cursorborderradius:'0',background:'#404040',spacebarenabled:false,cursorborder:'',zindex:'1000'});
		this.edit.html(this.$textarea.val());
		this._createBtn();
	};

	EditShell.prototype = {
		_createBtn:function(){
			var head = this.$el.find('.panel-heading'),edit=this.edit,shell=this;
			$('<a href="javascript:void(0);" style="padding:5px;"><i class="fa fa-bold"></i></a>').click(function(){
				edit.bold();shell.$textarea.val(edit.html());}).appendTo(head).tooltip({title:'加粗'});
			$('<a href="javascript:void(0);" style="padding:5px;"><i class="fa fa-italic"></i></a>').click(function(){
				edit.italic();shell.$textarea.val(edit.html());}).appendTo(head).tooltip({title:'斜体'});
			$('<a href="javascript:void(0);" style="padding:5px;"><i class="fa fa-align-left"></i></a>').click(function(){
				edit.left();shell.$textarea.val(edit.html());}).appendTo(head).tooltip({title:'左对齐'});
			$('<a href="javascript:void(0);" style="padding:5px;"><i class="fa fa-align-center"></i></a>').click(function(){
				edit.center();shell.$textarea.val(edit.html());}).appendTo(head).tooltip({title:'居中'});
			$('<a href="javascript:void(0);" style="padding:5px;"><i class="fa fa-align-right"></i></a>').click(function(){
				edit.right();shell.$textarea.val(edit.html());}).appendTo(head).tooltip({title:'右对齐'});
			$('<a href="javascript:void(0);" style="padding:5px;"><i class="fa fa-eraser"></i></a>').click(function(){
				edit.removeFormat();shell.$textarea.val(edit.html());}).appendTo(head).tooltip({title:'清除格式'});;
			$('<a href="javascript:void(0);" style="padding:5px;"><i class="fa fa-indent"></i></a>').click(function(){
				edit.indent();shell.$textarea.val(edit.html());}).appendTo(head).tooltip({title:'缩进'});
			$('<a href="javascript:void(0);" style="padding:5px;"><i class="fa fa-outdent"></i></a>').click(function(){
				edit.outdent();shell.$textarea.val(edit.html());}).appendTo(head).tooltip({title:'移除缩进'});
		}
	}
	
	
	$.fn.jfEdit = function(){
		var args = Array.prototype.slice.call(arguments, 0);
		var value = undefined;
		this.each(function () {
			var $this = $(this);
			if (args.length === 0 || typeof(args[0]) === "object") {
				opts = args.length === 0 ? {} : $.extend({}, args[0]);
				value = new EditShell(this,opts);  //创建控件
				$this.data(KEY,value);
			}else if (typeof(args[0]) === "string"){
				var entity = $this.data(KEY);
                if(entity === undefined){return;}
                value = entity[args[0]].apply(entity, args.slice(1));
			}else{
				 throw 'Invalid arguments to '+KEY+' plugin: ' + args;
			}
	    });
	    return (value === undefined) ? this : value;
	};
	
	$.fn.jfEdit.Constructor = EditShell;
	
})(window.jQuery)